﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using IntroduceCompany.Singleton;
using System.IO;
using IntroduceCompany.Util;
using System.ComponentModel.DataAnnotations;
using System.Data.Linq;
using IntroduceCompany.DTO;

namespace IntroduceCompany.Models
{


    public class ProductListView_Validation
    {
        //[System.ComponentModel.DataAnnotations.MetadataType(typeof(IntroduceCompany.Models.ProductListView_Validation))]

        [Required(ErrorMessage = "Mã sản phẩm phải có.")]
        [RegularExpression(ConstantClass.testProductCode, ErrorMessage = "Mã sản phẩm chỉ được dùng chử, số, \"_\", \"-\" và \".\" \nVd: CH-10.12" )]
        public String ProductID { get; set; }


        [Required(ErrorMessage = "Giá sản phẩm phải có.")]
        [RegularExpression(ConstantClass.testPositiveInteger, ErrorMessage = "Giá sản phẩm phải là số nguyên và lớn hơn 0.")]
        public String ProductPrice { get; set; }

        [Required(ErrorMessage = "Tên sản phẩm phải có.")]
        public String ProductName { get; set; }

    }


    public class ProductModels
    {

        private GeneralClass generalClass = new GeneralClass();
        private ThumbnailClass _thumbnailClass = new ThumbnailClass();


        /// <summary>
        /// Get All Product filter by language and product type
        /// </summary>
        /// <param name="languageID"></param>
        /// <returns></returns>
        internal IQueryable<ProductListView> GetAllProductList(String languageID, String productTypeID)
        {
            if (languageID == ConstantClass.markViewAllLanguage && Convert.ToInt16(productTypeID) == 0)
            {
                return (DataSingleton.GetInstance().ProductListViews.OrderByDescending(product => product.CreateDate));
            }
            else if (languageID != ConstantClass.markViewAllLanguage && Convert.ToInt16(productTypeID) == 0)
            {
                return (DataSingleton.GetInstance().ProductListViews.Where(product => product.ProductLanguageID == languageID)
                    .OrderByDescending(product => product.CreateDate));
            }
            else if (languageID == ConstantClass.markViewAllLanguage && Convert.ToInt16(productTypeID) != 0)
            {
                return (DataSingleton.GetInstance().ProductListViews.Where(product => product.ProductTypeID == Convert.ToInt16(productTypeID)
                    || product.Superior == Convert.ToInt16(productTypeID)).OrderByDescending(product => product.CreateDate));
            }
            else
            {
                return (DataSingleton.GetInstance().ProductListViews.Where(product => product.ProductLanguageID == languageID
                    && (product.ProductTypeID == Convert.ToInt16(productTypeID) || product.Superior == Convert.ToInt16(productTypeID)))
                    .OrderByDescending(product => product.CreateDate));
            }
        }


        /// <summary>
        /// Get Product Type from MenuListView with ViewAll 
        /// </summary>
        /// <param name="languageID"></param>
        /// <returns></returns>
        internal List<ProductTypeView> GetProductTypeList()
        {
            //Add menu "None" with ID = 0
            ProductTypeView tempProductType = new ProductTypeView();
            tempProductType.MenuListID = 0;
            tempProductType.MenuName = "Xem tất cả";

            List<ProductTypeView> productTypeList = new List<ProductTypeView>();
            productTypeList.Add(tempProductType);

            productTypeList.AddRange(DataSingleton.GetInstance().ProductTypeViews.Where(menu => menu.LanguageID == ConstantClass.mainLanguageID));

            return (productTypeList );
        }


        /// <summary>
        /// Get Product Type from MenuListView
        /// </summary>
        /// <param name="languageID"></param>
        /// <returns></returns>
        internal List<ProductTypeView> GetProductTypeListForEdit(String languageID)
        {
            return (DataSingleton.GetInstance().ProductTypeViews.Where(menu => menu.LanguageID == languageID).ToList());
        }

        /// <summary>
        /// Get Product Status List
        /// </summary>
        /// <param name="productLanguageID"></param>
        /// <returns></returns>
        internal List<ProductStatusView> GetProductStatusList(String languageID)
        {
            return (DataSingleton.GetInstance().ProductStatusViews.Where(status => status.LanguageID == languageID).ToList());
        }


        /// <summary>
        /// Delete Product
        /// </summary>
        /// <param name="productID"></param>
        internal void DeleteProduct(String productID,  String fullImagePath)
        {
            Product tempProduct = DataSingleton.GetInstance().Products.SingleOrDefault(product => product.ProductID == productID);

            try
            {
                IQueryable<ProductImage> proImages = DataSingleton.GetInstance().ProductImages.Where(i => i.ProductID == productID);

                foreach (ProductImage image in proImages)
                {
                    //Delete physical main image and thumbnail image of product
                    if (image.ProductImageName != "")
                    {
                        string mainProductImagePath = fullImagePath + image.ProductImageName;
                        if (File.Exists(mainProductImagePath))
                            File.Delete(mainProductImagePath);

                        string thumbnailProductImagePath = fullImagePath + "thumbnail/" + image.ProductImageName;
                        if (File.Exists(thumbnailProductImagePath))
                            File.Delete(thumbnailProductImagePath);
                    }

                }

                
            }
            catch (Exception ex) { Console.WriteLine(ex.Message); };

            DataSingleton.GetInstance().Products.DeleteOnSubmit(tempProduct);
            DataSingleton.GetInstance().Products.Context.SubmitChanges();
        }


        /// <summary>
        /// Change product state that is visible or not
        /// </summary>
        /// <param name="productID"></param>
        /// <param name="productVisible"></param>
        internal void ChangeProductVisible(String productID, bool productVisible)
        {
            Product tempProduct = DataSingleton.GetInstance().Products.SingleOrDefault(product => product.ProductID == productID);
            tempProduct.Visible = !productVisible;

            DataSingleton.GetInstance().Products.Context.SubmitChanges();
        }


        /// <summary>
        /// Get details of a product
        /// </summary>
        /// <param name="productID"></param>
        /// <param name="productLanguageID"></param>
        /// <returns></returns>
        internal ProductListView GetProductDetails(String productID, String productLanguageID)
        {
            return (DataSingleton.GetInstance().ProductListViews.SingleOrDefault(product => product.ProductID == productID && product.ProductLanguageID == productLanguageID));
        }


        /// <summary>
        /// Get details of a product expect product is disable
        /// </summary>
        /// <param name="productID"></param>
        /// <param name="productLanguageID"></param>
        /// <returns></returns>
        internal ProductListView GetProductDetails_Frontend(String productID, String productLanguageID)
        {
            return (DataSingleton.GetInstance().ProductListViews.SingleOrDefault(product => product.ProductID == productID && product.ProductLanguageID == productLanguageID 
                && product.Visible == true ));
        }


        /// <summary>
        /// Check a product that has specific language or not
        /// </summary>
        /// <param name="productListView"></param>
        /// <returns>True is exist, False is not</returns>
        internal bool CheckProductLanguageTable(ProductListView productListView)
        {
            return (DataSingleton.GetInstance().Product_Ls.Any(product => product.ProductID == productListView.ProductID 
                && product.LanguageID == productListView.ProductLanguageID));
        }


        /// <summary>
        /// Update product details
        /// </summary>
        /// <param name="productListView"></param>
        internal bool UpdateProduct(ProductListView productListView, String username)
        {
            try
            {
                Product_L tempProduct_L = DataSingleton.GetInstance().Product_Ls.SingleOrDefault(productL => productL.ProductID == productListView.ProductID
        && productL.LanguageID == productListView.ProductLanguageID);
                tempProduct_L.ProductName = productListView.ProductName.Trim();
                tempProduct_L.ProductDescription = productListView.ProductDescription.Trim();

                Product tempProduct = DataSingleton.GetInstance().Products.SingleOrDefault(product => product.ProductID == productListView.ProductID);
                tempProduct.ProductTypeID = productListView.ProductTypeID;
                tempProduct.ProductPrice = productListView.ProductPrice;
                tempProduct.ProductStatusID = productListView.ProductStatusID;
                tempProduct.UserName = username;
                tempProduct.UpdateDate = DateTime.Now;

                DataSingleton.GetInstance().Products.Context.SubmitChanges();
                DataSingleton.GetInstance().Product_Ls.Context.SubmitChanges();
                DataSingleton.GetInstance().Refresh(RefreshMode.KeepChanges, tempProduct_L);


            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
            return true;
        }


        /// <summary>
        /// Insert into table product language
        /// </summary>
        /// <param name="productListView"></param>
        internal bool InsertProductLanguage(ProductListView productListView)
        {
            try
            {
                DataSingleton.GetInstance().sp_Product_L_Insert(productListView.ProductID, productListView.ProductLanguageID,
                    productListView.ProductName.Trim(), productListView.ProductDescription.Trim());

                //Refresh product table to get new values from database
                DataSingleton.GetInstance().Refresh(RefreshMode.OverwriteCurrentValues, DataSingleton.GetInstance().Products);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
            return true;
        }



        /// <summary>
        /// Insert Product information into table Product and Product_L
        /// </summary>
        /// <param name="productListView"></param>
        internal bool CreateProduct(ProductListView productListView, String username)
        {
            try
            {
                DataSingleton.GetInstance().sp_ProductInsert(productListView.ProductID, productListView.ProductTypeID, productListView.ProductPrice,
                    productListView.ProductStatusID, username);

                DataSingleton.GetInstance().sp_Product_L_Insert(productListView.ProductID, productListView.ProductLanguageID, productListView.ProductName.Trim(),
                    productListView.ProductDescription.Trim());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
            return true;
        }



        /// <summary>
        /// Check duplicate productID (True is duplicate, False is none)
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        internal bool IsDuplicateProductID(String productID)
        {
            return (DataSingleton.GetInstance().Products.Any(product => product.ProductID == productID ));
        }

/////
        /// <summary>
        /// Get new products list filter by ProductDate
        /// </summary>
        /// <returns></returns>
        internal IQueryable<ProductListView> GetNewProductList(int numberOfProduct, String languageID)
        {
            return (DataSingleton.GetInstance().ProductListViews.Where(product => product.ProductLanguageID == languageID && product.Visible == true)
                .OrderByDescending(product => product.CreateDate).Take(numberOfProduct));
        }


        /// <summary>
        /// Get products have biggest view number filter by langugage
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        internal IQueryable<ProductListView> GetBiggestViewNumberProductList(int numberOfProduct, String languageID)
        {
            return (DataSingleton.GetInstance().ProductListViews.Where(product => product.ProductLanguageID == languageID && product.Visible == true)
                .OrderByDescending(product => product.ViewNumber).Take(numberOfProduct));
        }


        /// <summary>
        /// Get product list filter by Product type, language and visible is true
        /// </summary>
        /// <param name="productTypeID"></param>
        /// <returns> aaaaaa </returns>
        internal IQueryable<ProductListView> GetOnePageProductListByType(int productTypeID, String languageID, String currentPage, int step)
        {
            int startRowIndex = (Convert.ToInt16(currentPage) - 1) * step;

            return (DataSingleton.GetInstance().ProductListViews.Where(product =>  (product.ProductTypeID == productTypeID  || product.Superior == productTypeID) && 
                product.ProductLanguageID == languageID && product.Visible == true).OrderByDescending(product => product.ProductID).Skip(startRowIndex).Take(step));
        }


        /// <summary>
        /// Get all images of a product
        /// </summary>
        /// <param name="productID"></param>
        /// <returns></returns>
        internal IQueryable<ProductImage> GetProductImages(String productID)
        {
            return (DataSingleton.GetInstance().ProductImages.Where(img => img.ProductID == productID).OrderBy(img => img.ProductImageID));
        }

        /// <summary>
        /// Upload Image of product
        /// </summary>
        /// <param name="productID"></param>
        /// <param name="fileToUpload"></param>
        /// <param name="p"></param>
        internal void UploadProductImage(String productID, IEnumerable<HttpPostedFileBase> fileToUpload, string path)
        {
            string uploadPath1 = path;
            string uploadPath2 = path + "/thumbnail/";
            //Guid guid;
            string name = "";
            string fullName = "";
            string fileExtension = "";
            string seolProductUrl = DataSingleton.GetInstance().Product_Ls.SingleOrDefault(p => p.ProductID == productID 
                && p.LanguageID == ConstantClass.mainLanguageID).ProductSeoUrl;


            foreach (var file in fileToUpload)
            {
                //guid = System.Guid.NewGuid();
                //name = productID + "-" + guid.ToString();
                name = seolProductUrl + "-" + DateTime.Now.Ticks;
                name = name.Length > 190 ? name.Substring(0, 190) : name;

                fileExtension = Path.GetExtension(file.FileName).ToLower().Trim();
                fullName = name + fileExtension;

                ProductImage imageRecord = new ProductImage();
                imageRecord.ProductID = productID;
                imageRecord.ProductImageName = fullName;

                DataSingleton.GetInstance().ProductImages.InsertOnSubmit(imageRecord);
                _thumbnailClass.UploadImage1(file, uploadPath1, 600, file.FileName, name);
                _thumbnailClass.UploadImage1(file, uploadPath2, 100, file.FileName, name);
            }
            DataSingleton.GetInstance().SubmitChanges();
        }


        /// <summary>
        /// Delete Image of product
        /// </summary>
        /// <param name="imageID"></param>
        /// <param name="path"></param>
        internal void ProductImageDelete(int imageID, string path)
        {
            ProductImage tempImage = DataSingleton.GetInstance().ProductImages.SingleOrDefault(u => u.ProductImageID == imageID);
            DataSingleton.GetInstance().ProductImages.DeleteOnSubmit(tempImage);
            DataSingleton.GetInstance().SubmitChanges();

            string path1 = path ;
            string path2 = path + "/thumbnail/";

            if (tempImage.ProductImageName != "")
            {
                string LocalFile = path1 + tempImage.ProductImageName;
                if (File.Exists(LocalFile))
                    File.Delete(LocalFile);

                LocalFile = path2 + tempImage.ProductImageName;
                if (File.Exists(LocalFile))
                    File.Delete(LocalFile);
            }

        }


        /// <summary>
        /// Get one record of product table filter by productID
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        internal Product GetProductByProductID(String productID)
        {
            return DataSingleton.GetInstance().Products.SingleOrDefault(pr => pr.ProductID == productID);
        }


        /// <summary>
        /// Get ProductID based on ProductSeoUrl
        /// </summary>
        /// <param name="productSeoUrl"></param>
        /// <returns></returns>
        internal String GetProductIDByProductSeoUrl(String productSeoUrl)
        {
            return DataSingleton.GetInstance().Product_Ls.First(pr => pr.ProductSeoUrl == productSeoUrl).ProductID;
        }
////
        /// <summary>
        /// Get ProductSeoUrl based on ProductID and Language
        /// </summary>
        /// <param name="productSeoUrl"></param>
        /// <returns></returns>
        internal String GetProductSeoUrl_By_ProductID_LanguageID(String productID, String languageID)
        {
            //return DataSingleton.GetInstance().ProductListViews.First(pr => pr.ProductID == productID && pr.ProductLanguageID == languageID).ProductSeoUrl;
            return DataSingleton.GetInstance().Product_Ls.First(pr => pr.ProductID == productID && pr.LanguageID == languageID).ProductSeoUrl;
        }


        /// <summary>
        /// Caculate total record in one product type
        /// </summary>
        /// <param name="menuListID"></param>
        /// <param name="languageID"></param>
        /// <returns></returns>
        internal int Frontend_GetTotalRowsOneProductTypeOneLanguage(int menuListID, string languageID)
        {
            return DataSingleton.GetInstance().ProductListViews.Where(pro => pro.ProductTypeID == menuListID && pro.ProductLanguageID == languageID
                && pro.Visible == true).Count();

        }

        /// <summary>
        /// Update view number of product increase by 1
        /// </summary>
        /// <param name="productID"></param>
        internal void UpdateViewNumberOfProduct(string productID)
        {
            try
            {
                Product tempProduct = DataSingleton.GetInstance().Products.SingleOrDefault(p => p.ProductID == productID);
                tempProduct.ViewNumber = tempProduct.ViewNumber + 1;
                DataSingleton.GetInstance().Products.Context.SubmitChanges();

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }


        /// <summary>
        /// Check product of this language that is existed or not. True is existed and otherwise
        /// </summary>
        /// <param name="productListView"></param>
        /// <returns></returns>
        internal bool CheckProductLanguageIsExisted(String productID, String languageID)
        {
            return DataSingleton.GetInstance().Product_Ls.Any(p => p.ProductID == productID && p.LanguageID == languageID);
        }


        /// <summary>
        /// Check product seourl has this language or not. True is existed and otherwise
        /// </summary>
        /// <param name="productID"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        internal bool CheckProduct_WithLanguage(string productID, String languageID)
        {
            return DataSingleton.GetInstance().Product_Ls.Any(p => p.ProductID == productID && p.LanguageID == languageID);
        }
    }
}